package com.kyle.redpacket.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 二倍均值法的代码实战
 *
 * 核心思想是根据每次剩余的总金额M和剩余人数N,执行M/N×2得到一个边界值E，然后制定一个从0到E的随机去见，
 * 在这个区间内将产生一个随机金额R，后续总金额M将根欣慰M-R，剩余人数N更新为N-1，
 * 重复上述步骤直至N=0
 *
 * @author: zhonglinsen
 * @date: 2019/3/15
 */
public class RedPacketUtil {

    /**
     * 发红包算法，金额参数以分为单位
     * @param totalAmount 红包总金额，单位为分
     * @param totalPeopleNum 总人数
     * @return
     */
    public static List<Long> divideRedPackage(Long totalAmount, Long totalPeopleNum) {
        //用于存储每次产生的小红包随机金额列表，金额单位为分
        List<Long> amountList = new ArrayList<>();

        //判断总金额和总人数参数的合法性
        if (totalAmount>0 && totalPeopleNum>0){
            //记录剩余的总金额，初始化时即为红包的总金额
            long restAmount = totalAmount;
            //记录剩余的总人数，初始化时即为指定的总人数
            long restPeopleNum = totalPeopleNum;
            //定义产生随机数的实例对象
            Random random = new Random();
            //不断循环遍历、迭代更新地产生随机金额，直到N-1≤0
            for (int i = 0; i < totalPeopleNum - 1; i++) {
                /*
                 随机范围：[1，剩余人均金额的两倍)，左闭右开
                 amount即产生的随机金额R，单位为分
                 */
                long amount =(long) random.nextInt((int)(restAmount / restPeopleNum) * 2 - 1) + 1;
                //更新剩余的再陪你挂机呢M=M-R
                restAmount -= amount;
                //更新剩余的总人数N=N-1
                restPeopleNum--;
                //将产生的随机金额添加进列表中
                amountList.add(amount);
            }
            //循环完毕，剩余的金额即为最后一个随机金额，也需要将其添加进列表中
            amountList.add(restAmount);
        }
        //将最终产生的随机金额列表返回
        return amountList;
    }

}
